export const isFirefox = /firefox/.test(window.navigator.userAgent.toLowerCase());
export const {
    clone, startAnim, isArray, setPropertyValue, getPropertyValue, getShape3dModel, getImage, unionPoint, grow,
    toRoundedCorner, appendToScreen, removeHTML, toColorData, getDistance, isFunction, xhrLoad, parse
} = ht.Default;

let opacityMap = {};
const optionProperties = ['shape3d', 'all', 'left', 'right', 'top', 'bottom', 'front', 'back', 'from', 'to'];
const nodeOpacity = 0.04;
export function saveNodeOpacity(dm, ignoreNode) {
    const opacity = nodeOpacity
    dm.each(function (d) {
        const id = d.getId()
        if (!opacityMap[id]) {
            opacityMap[id] = ht.Default.clone(d.getStyleMap())
        } else if (d === ignoreNode) {
            d.setStyleMap(ht.Default.clone(opacityMap[id]))
        }

        if (ht.Default.isArray(ignoreNode)) {
            if (ignoreNode.indexOf(d) >= 0) return
        }
        else if (d === ignoreNode) {
            return
        }

        optionProperties.forEach(k => {
            d.s(k + '.opacity', opacity)
            d.s(k + '.transparent', true)
        })

        d.s({
            '3d.selectable': false,
            batch: undefined,
        })
    })
}

export function restoreNodeOpacity(dm) {
    dm.each(d => {
        const style = opacityMap[d.getId()];
        d.setStyleMap(ht.Default.clone(style));
    });
}

/**
 * @description: 经纬度转换为3d坐标
 * @param {longitude,dimension,r} 经度 维度 地球模型半径
 * @return: [x,y,z] 3d坐标
 */
export function to3dPoint(longitude, dimension, r = 400) {
    let y = r * Math.sin((Math.PI / 180) * dimension);
    let temp = r * Math.cos((Math.PI / 180) * dimension);
    let x = temp * Math.sin((Math.PI / 180) * longitude);
    let z = temp * Math.cos((Math.PI / 180) * longitude);
    return [x, y, z];
}

export function formatDate(date, formatStr) {
    var str = formatStr;
    var Week = ['日', '一', '二', '三', '四', '五', '六'];

    str = str.replace(/yyyy|YYYY/, date.getFullYear());
    str = str.replace(/yy|YY/, (date.getYear() % 100) > 9 ? (date.getYear() % 100).toString() : '0' + (date.getYear() % 100));
    var month = date.getMonth() + 1;
    str = str.replace(/MM/, month > 9 ? month.toString() : '0' + month);
    str = str.replace(/M/g, month);

    str = str.replace(/w|W/g, Week[date.getDay()]);

    str = str.replace(/dd|DD/, date.getDate() > 9 ? date.getDate().toString() : '0' + date.getDate());
    str = str.replace(/d|D/g, date.getDate());

    var hour = date.getHours();
    str = str.replace(/HH/, hour > 9 ? hour.toString() : '0' + hour);
    str = str.replace(/H/g, hour);

    str = str.replace(/A/g, hour >= 12 ? 'PM' : 'AM');
    str = str.replace(/Aa/g, hour >= 12 ? 'pm' : 'am');

    hour = hour > 12 ? hour % 12 : hour;
    str = str.replace(/hh/, hour > 9 ? hour.toString() : '0' + hour);
    str = str.replace(/h/g, hour);

    str = str.replace(/mm/, date.getMinutes() > 9 ? date.getMinutes().toString() : '0' + date.getMinutes());
    str = str.replace(/m/g, date.getMinutes());
    str = str.replace(/ss|SS/, date.getSeconds() > 9 ? date.getSeconds().toString() : '0' + date.getSeconds());
    str = str.replace(/s|S/g, date.getSeconds());

    return str;
}

export const deserialize = (function () {
    let cacheMap = {};

    /**
     * 加载 json 并反序列化
     */
    return function (view, url, cb, notUseCache, reset = true) {
        const cache = !notUseCache;

        let cacheContent;
        if (cache && cacheMap[url]) {
            view.view.deserialize(cacheMap[url], {
                reset,
                finishFunc: (json, dm, view, list) => {
                    if (isFunction(cb)) cb(json, dm, view, list, cache);
                }
            })
            return;
            // cacheContent = cacheMap[url];
        }

        xhrLoad(url, (t) => {
            const json = parse(t);
            if (!cacheContent) cacheMap[url] = json;
            if (!view.active) return;
            // 不使用缓存，重新加载
            view.view.deserialize(json, {
                reset,
                finishFunc: (json, dm, view, list) => {
                    if (isFunction(cb)) cb(json, dm, view, list, cache);
                }
            });
        });
    }
})();


const CHINA_CENTER = { x: 11131949, y: 3503549 },
    MAX_P = 139920037508;
// 经纬度转坐标
export function latLonToLogical(lon, lat) {
    lon *= 1;
    lat *= 1;
    let p = { x: 0, y: 0 };
    p.x = lon * MAX_P / 180.0;
    let y = Math.log(Math.tan((90.0 + lat) * Math.PI / 360.0)) / (Math.PI / 180.0);
    p.y = y * MAX_P / 180.0;
    p.x = p.x - CHINA_CENTER.x;
    p.y = p.y - CHINA_CENTER.y;
    p.x = p.x / 3000.0;
    p.y = p.y / 3000.0;
    p.y = 0 - p.y;
    p.e = 0;
    return p;
}
// 坐标转经纬度
export function logicalToLonLat(p) {
    p.y = 0 - p.y;
    p.y *= 3000.0;
    p.x *= 3000.0;
    p.x = p.x + CHINA_CENTER.x;
    p.y = p.y + CHINA_CENTER.y;
    var y = p.y * 180.0 / MAX_P;
    var lon = p.x * 180.0 / MAX_P;
    var lat = Math.atan(Math.pow(Math.E, y * (Math.PI / 180.0))) * 360.0 / Math.PI - 90;
    return {
        lon: lon.toFixed(6) * 1,
        lat: lat.toFixed(6) * 1
    }
}

/**
 * 判断是否是空对象
 * @param {Object} obj 
 */
export function isEmpty(obj) {
    return obj === null || obj === undefined;
}

/**
 * 返回一个指定范围内的随机数
 * @param {Number} min 最小值
 * @param {Number} [max] 最大值，如果不传则第一个参数为最大值，最小值默认0
 */
export const random = function (min, max) {
    if (isEmpty(max)) {
        max = min;
        min = 0;
    }

    let range = max - min;
    return Math.random() * range + min;
}

/**
 * 将一个字符串中的数字单独取出来组成一个新数字
 *
 * @export
 * @param {*} str
 * @return {*} 
 */
export function extractNumbersFromString(str) {
    // 使用正则表达式匹配字符串中的所有数字
    const numbers = str.match(/\d+/g);

    if (!numbers) {
        // 如果没有匹配到任何数字，返回null或空数组
        return null;
    }

    // 将匹配到的数字数组拼接成一个新的字符串
    const numberString = numbers.join('');

    // 如果需要将其转换为一个数字类型，可以使用parseInt或parseFloat
    const number = parseInt(numberString, 10);

    return number;
}